<template>
  <div style="width: 500px">
    <el-input
      placeholder="请输入部门名称进行搜索..."
      prefix-icon="el-icon-search"
      v-model="filterText"
    >
    </el-input>
    <!-- filterNode拦截节点的方法 -->
    <!-- :filter-node-method="filterNode" 调用filterNode事件 -->
    <el-tree
      :data="deps"
      :props="defaultProps"
      :filter-node-method="filterNode"
      :expand-on-click-node="false"
      ref="tree"
    >
      <!-- slot-scope可以自定义竖节点里面的内容  node:当前节点里面的node对象 ,data自己后端返回的对应的数据 -->
      <span
        class="custom-tree-node"
        slot-scope="{ data }"
        style="display: flex; justify-content: space-between; width: 100%"
      >
        <span>{{ data.name }}</span>
        <span>
          <el-button
            type="primary"
            size="mini"
            class="depBtn"
            @click="() => showAddDep(data)"
          >
            添加部门
          </el-button>
          <el-button
            type="danger"
            size="mini"
            class="depBtn"
            @click="() => deleteDep(data)"
          >
            删除部门
          </el-button>
        </span>
      </span>
    </el-tree>
    <el-dialog title="添加部门" :visible.sync="dialogVisible" width="30%">
      <div>
        <table>
          <tr>
            <td>
              <el-tag>上级部门</el-tag>
            </td>
            <td>{{ pname }}</td>
          </tr>
          <tr>
            <td>
              <el-tag>部门名称</el-tag>
            </td>
            <td>
              <el-input
                v-model="dep.name"
                placeholder="请输入部门名称....."
              ></el-input>
            </td>
          </tr>
        </table>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="doAddDep">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "DepMana",
  data() {
    return {
      filterText: "",
      // 要展示的数据deps 后端传来的
      deps: [],
      defaultProps: {
        children: "children",
        label: "name",
      },
      dialogVisible: false,
      // 要传输给后端的数据对象dep
      dep: {
        name: "",
        parentId: -1, // 默认是-1即可
      },
      pname: "", // 上级部门名称
    };
  },
  // 监控val值的变化 该值就是v-model="filterText"绑定的值，绑定的值变化之后会去找树形控件，去调用filterNode方法
  // 观察者事件 filterText; watch会观察filterText里面的值val，找到对应的树形控件,然后把值传进来
  //  调用的其实是       :filter-node-method="filterNode"
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },

  mounted() {
    this.initDeps();
  },
  methods: {
    // 手动删除
    removeDepFromDeps(p, deps, id) {
      for (let i = 0; i < deps.length; i++) {
        // 注意d d本身就是一个父对象
        let d = deps[i];
        if (d.id == id) {
          // 指定2个参数：要删除的第一项的位置和要删除项的项数。例如，splice(0,2)会删除数组中的前两项。
          deps.splice(i, 1); // 删除
          // 子部门下（本身没下一级子部门情况下）添加一新子部门 对应的isparent也变换了，如果再删除该部门下的子部门，该部门的isparent需要刷新
          // 位于循环下面，deps已经处于在要删除的部门中 所以如果deps删除了 那么deps=0
          if (deps.length == 0) {
            // 如果子部门=0 修改isParent
            p.isParent = false;
          }
          return;
        } else {
          // 递归
          // p的值传递给d  d,d.children,id 实参
          this.removeDepFromDeps(d, d.children, id);
        }
      }
    },

    // deps 查询到的整个数组
    // 手动添加部门的方法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    // 暂时理解 deps..父部门 ;dep..  表示要添加的部门 输入的数据
    addDep2Deps(deps, dep) {
      for (let i = 0; i < deps.length; i++) {
        // d 父部门
        let d = deps[i];
        if (d.id == dep.parentId) {
          // concat() 方法用于连接两个或多个字符串
          d.children = d.children.concat(dep); // 相当于重新赋值
          // bug 添加解决isParent
          if (d.children.length > 0) {
            d.isParent = true;
          }
          return;
        } else {
          // 如果不是的话就去子部门循环
          this.addDep2Deps(d.children, dep);
        }
      }
    },
    // 初始化要传出的数据对象
    initDep() {
      this.dep = {
        name: "",
        parentId: -1,
      };
      this.pname = "";
    },
    doAddDep() {
      this.postRequest("/system/basic/department/", this.dep).then((resp) => {
        if (resp) {
          // 手动去插入部门 【resp.obj 添加完后的数据】  手动显示 刚添加的数据到树形控件正确位置
          this.addDep2Deps(this.deps, resp.obj);
          this.dialogVisible = false;
          this.initDep();
        }
      });
    },
    showAddDep(data) {
      this.dep.parentId = data.id; // dep对象拿到（赋值传输）parentid
      this.pname = data.name; // 拿到上级部门名称
      this.dialogVisible = true;
    },
    deleteDep(data) {
      // 如果isParent... bug 添加要改变isParent
      if (data.isParent) {
        this.$message.error("父部门删除失败！");
      } else {
        // Vue 实例还暴露了一些有用的实例属性与方法。它们都有前缀 $，以便与用户定义的属性区分开来。
        this.$confirm(
          "此操作将永久删除该【" + data.name + "】部门, 是否继续?",
          "提示",
          {
            confirmButtonText: "确定",
            cancelButtonText: "取消",
            type: "warning",
          }
        )
          .then(() => {
            this.deleteRequest("/system/basic/department/" + data.id).then(
              (resp) => {
                if (resp) {
                  // 由于董事会上面没有父部门 所以传一个null去递归 自己会去zh会去zhao
                  this.removeDepFromDeps(null, this.deps, data.id);
                }
              }
            );
          })
          .catch(() => {
            this.$message({
              type: "info",
              message: "已取消删除",
            });
          });
      }
    },

    // 参上 :data="deps"
    initDeps() {
      this.getRequest("/system/basic/department/").then((resp) => {
        if (resp) {
          this.deps = resp;
        }
      });
    },
    // value是传过来的值,data就是一行的数据 在哪个目录下面就是哪个目录下的整条数据
    // 对树的节点进行筛选时执行的方法
    filterNode(value, data) {
      // 如果把搜索框的值清空了（没值），那整棵树形控件就会全部展示开来
      if (!value) return true; // 如果不在返回true; true表示这个节点可以去展示
      // 如果有值  返回true展示，false隐藏
      return data.name.indexOf(value) !== -1; // 判断是否包含该值 和-1是不是相等的 。如果true这个节点就可以展示，如果false这个节点就会被隐藏
    },
  },
};
</script>

<style scoped>
.depBtn {
  padding: 2px;
}
</style>